﻿using System;
using System.Collections.Concurrent;
using System.Diagnostics;
using System.IO.Ports;
using System.Threading.Tasks;
using ToolsetL.Modle;

namespace ToolsetL.WeighingInstruments
{
    /// <summary>
    /// 传一个范围进来，然后取这个范围内的稳定值(连续N次值无变化)
    /// </summary>
    internal class WeighingInstruments : IDisposable
    {
        public SerialPort SerialPort { get; private set; }
        private readonly SerialPortConfiguration serialPortConfiguration;
        private readonly decimal upperLimit;
        private readonly decimal lowerLimit;
        private readonly BlockingCollection<decimal> queue = new BlockingCollection<decimal>();

        public WeighingInstruments(SerialPortConfiguration serialPortConfiguration, decimal upperLimit, decimal lowerLimit)
        {
            this.serialPortConfiguration = serialPortConfiguration;
            this.upperLimit = upperLimit;
            this.lowerLimit = lowerLimit;
        }

        public void Open()
        {
            SerialPort = new SerialPort(serialPortConfiguration.COM, serialPortConfiguration.BaudRate, serialPortConfiguration.Parity, serialPortConfiguration.Databits, serialPortConfiguration.Stopbits);
            SerialPort.Open();
        }

        public async Task<decimal> GetStableWeightAsync(int requiredStableReads)
        {
            if (SerialPort != null && SerialPort.IsOpen)
            {
                SerialPort.DataReceived += SerialPort_DataReceived;

                decimal lastWeight = 0;
                int stableCount = 1;

                return await Task.Run(() =>
                {
                    try
                    {
                        foreach (var data in queue.GetConsumingEnumerable())
                        {
                            if (data == lastWeight)
                            {
                                stableCount++;
                                if (stableCount >= requiredStableReads)
                                {
                                    SerialPort.DataReceived -= SerialPort_DataReceived;
                                    return lastWeight;
                                }
                            }
                            else
                            {
                                stableCount = 1;
                                lastWeight = data;
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        Debug.WriteLine(ex.Message);    
                    }
                    throw new Exception("无法获取到有效的值");
                });
            }
            throw new Exception("SerialPort is null");
        }

        private void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            if (!(sender is SerialPort sp))
            {
                return;
            }

            string indata = sp.ReadExisting();

            if (!string.IsNullOrWhiteSpace(indata))
            {
                if (indata.Contains("="))
                {
                    string[] strings = indata.Split('=');

                    if (strings.Length == 2)
                    {
                        try
                        {
                            var data = decimal.Parse(strings[1]);

                            if (data < upperLimit && data > lowerLimit)
                            {
                                queue.TryAdd(data);
                            }
                        }
                        catch
                        {

                        }
                    }
                }
            }
        }

        public void Close()
        {
            try
            {
                if (SerialPort != null)
                {
                    SerialPort.Close();
                    SerialPort.Dispose();
                    queue.CompleteAdding();
                    queue.Dispose();
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }

        public void Dispose()
        {
            Close();
        }

    }
}
